package zhongbo.java.air.monitor.web.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import zhongbo.java.air.monitor.dto.PointDto;
import zhongbo.java.air.monitor.model.AirAlertLog;

import zhongbo.java.air.monitor.model.AirAlertZone;
import zhongbo.java.air.monitor.service.AirAlertZoneService;
import zhongbo.java.air.monitor.service.IAirAlertLogService;
import zhongbo.java.air.monitor.service.IJtsService;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class AlertZoneWebSocket extends TextWebSocketHandler {

    private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();

    @Autowired
    private IJtsService jtsService;

    @Autowired
    private IAirAlertLogService<AirAlertLog> airAlertLogService;
//    @Autowired
//    private AirAlertZoneService<AirAlertZone> alertZoneService;

    @Autowired
    private AirAlertZoneService<AirAlertZone> alertZoneService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
    }

    public void broadcastAlert(AirAlertLog alertLog) throws IOException {
        String message = objectMapper.writeValueAsString(alertLog);
        log.info("广播告警日志记录: {}", message);
        for (WebSocketSession session : sessions) {
            if (session.isOpen()) {
                session.sendMessage(new TextMessage(message));
            }
        }
    }

    /**
     * 检查并广播告警日志记录
     * 适用场景：当飞机进入警戒区域时，系统会自动查询并广播告警日志记录
     *
     * @param json
     */
    public void checkAndBroadcastAlert(JSONObject json) {
        List<AirAlertZone> alertZones = alertZoneService.queryAll();
        if (alertZones.isEmpty()) {
            log.info("没有找到警戒区区域数据，结束告警判断");
            return;
        }

        // 获取 icao 并记录日志
        String icao = json.getStr("icao_code");
        log.info("获取到的 icao: {}", icao);

        // 查询5分钟内的告警日志记录
        String redisKey = "alert:history:lgh:" + icao;
        log.info("生成的 Redis 键: {}", redisKey);

        String recentAlertsJson = stringRedisTemplate.opsForValue().get(redisKey);
        if (recentAlertsJson != null) {
            log.info("找到5分钟内的告警日志记录，结束告警判断");
            return;
        }

        // 遍历警戒区，判断点位是否在警戒区域内
        for (AirAlertZone zone : alertZones) {
            List<PointDto> pointDtos = jtsService.parseAlertZoneVertices(zone.getVertices());
            boolean inAlertZone = jtsService.isInAlertZone(pointDtos, json.getDouble("longitude"), json.getDouble("latitude"));
            if (inAlertZone) {
                // 构建告警日志记录
                String triggerCoordinates = "{\"lon\":" + json.getDouble("longitude") + ",\"lat\":" + json.getDouble("latitude") + "}";
                String alertZoneCode = zone.getZoneCode();
                if (alertZoneCode == null || alertZoneCode.isEmpty()) {
                    alertZoneCode = "UNKNOWN";
                }
                if (alertZoneCode.length() > 20) {
                    alertZoneCode = alertZoneCode.substring(0, 20);
                }
                AirAlertLog alertLog = new AirAlertLog(
                        zone.getId(), // zoneId
                        icao, // icaoCode
                        zone.getZoneType(), // zoneType
                        alertZoneCode, // alertZoneCode
                        triggerCoordinates, // triggerCoordinates
                        json.getDate("timestamp"), // triggerTime
                        "未处理", // status
                        new Date(), // createTime
                        new Date() // updateTime

                );

                // 保存告警日志记录
                airAlertLogService.add(alertLog);
                System.out.println("保存告警日志：" + alertLog);

                // 将告警日志记录缓存到 Redis 中，并设置超时时间为 5 分钟
                String alertLogJson = JSONUtil.toJsonStr(alertLog);
                stringRedisTemplate.opsForValue().set(redisKey, alertLogJson, 5, TimeUnit.MINUTES);
                log.info("已将键 {} 存储到 Redis 中", redisKey);

                // 广播告警日志记录
                try {
                    broadcastAlert(alertLog);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }
}